/*
 * Copyright (C) 2008+ Spark Zheng
 *
 * src/test/test_htable.c
 *
 * build a htable for a dictory, and search for some thing,
 * then delete this thing, such a simple test.
 *
 *	dict format:
 *		中国    32915   N
 *		现在    14680   N
 *
 *  the same testing flow with test_hash.c
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>

#include "hash.h"
#include "htable.h"

#ifdef BUF_LEN
#undef BUF_LEN
#endif
#define BUF_LEN		1024
#define TEST_WORD	"中国"
#define DICT	"./data/dict_utf8_s"
//#define DICT	"./data/dict_utf8_m"
//#define DICT	"./data/dict_utf8"

typedef struct val {
	char		*key;
	uint32_t	visit;
	uint32_t	type;
} S_VAL;

static void _usage(void);
static int _compare(const void *one, const void *two);
static uint32_t _hash(const void *k, void *other);
static void _release_val(void *val);
static void _walker(const void *k, const void *v, void *arg);

static void _usage(void)
{
	fprintf(stdout, "Usage: \n" \
			"    test_htable_nomarena dict_len key.\n" \
			"    test_htable_marena dict_len key.\n");
	return;
}

static int _compare(const void *one, const void *two)
{
	const char *s_one = (const char *)one;
	const char *s_two = (const char *)two;
	
	while ((*s_one | *s_two) != 0) {
		if (*s_one < *s_two)
			return -1;
		else if (*s_one > *s_two)
			return 1;
		else {
			s_one++;
			s_two++;
		}
	}
	
	return 0;
}

static uint32_t _hash(const void *k, void *other)
{
	UNUSED_PARAM(other);
	const char *key = (const char *)k;
	uint32_t key_len = strlen(key);
	return one_at_a_time_hash(key, key_len);
}

static void _release_val(void *val)
{
	S_VAL *t = (S_VAL *)val;
	
	if (t == NULL) return;
	
	if (t->key != NULL) {
		free(t->key);
		t->key = NULL;
	}
	free(t);
	
	return;
}

static void _walker(const void *k, const void *v, void *arg)
{	
	fprintf(stdout, "walker: key is %s, v is %p, arg is %d.\n",
		(const char *)k, v, *(int *)arg);

	(*(int *)arg)++;
	
	return;
}

int main(int argc, char *argv[])
{
	int i = 0;
	htable_t *dict;
	uint32_t dict_len = 1113; /* a primer */
	char *keyword = TEST_WORD;
	FILE *fp;
	
	char buffer[BUF_LEN + 1];
	
	S_VAL *n = NULL;
	
	S_VAL *value;
	char *nat = NULL;
	char *key = NULL;
	size_t key_len = 0;
	
	if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') {
		_usage();
		return -1;
	}
	
	if (argc == 2) {
		if (atoi(argv[1]) != 0)
			dict_len = (uint32_t)atoi(argv[1]);
		else
			keyword = argv[1];
	} else if (argc == 3) {
		if (atoi(argv[1]) != 0)
			dict_len = (uint32_t)atoi(argv[1]);
		keyword = argv[2];
	}
	
	fprintf(stdout, "ht_table test begin with %u, keyword %s.\n",
		dict_len, keyword);
	
	dict = ht_init(dict_len, _hash, NULL, _compare, 0, _release_val);
	if (dict == NULL) {
		fprintf(stderr, "ht_init error.\n");
		return -2;
	}
	
	if ((fp = fopen(DICT, "r")) == NULL) {
		fprintf(stderr, "fopen error: %s\n", strerror(errno));
		ht_exit(dict);
		return -3;
	}
	
	memset(buffer, 0, BUF_LEN + 1);
	while (fgets(buffer, BUF_LEN, fp) != NULL) {
		key = strtok(buffer, "\r\n\t ");
		if (key == NULL) continue;
		
		key_len = strlen(key);
		value = (S_VAL *)calloc(1, sizeof(S_VAL));
		value->key = (char *)calloc(1, key_len + 1);
		memcpy(value->key, key, key_len);
		
		value->visit = (uint32_t)atoi(strtok(NULL, "\r\n\t "));
		nat = strtok(NULL, "\r\n\t ");
		value->type = 0;
		
		ht_set(dict, value->key, value);
		
		memset(buffer, 0, BUF_LEN);
	}
	
	fclose(fp);
	
	fprintf(stdout, "ht_table load successfully.\n");
	
	fprintf(stdout, "ht_table get '%s' now...\n", keyword);
	n = (S_VAL *)ht_get(dict, keyword);
	if (n == NULL) {
		fprintf(stdout, "ht_table get '%s' not exist.\n", keyword);
	} else {
		fprintf(stdout, "ht_table get '%s' successfully.\n", keyword);
		fprintf(stdout, "key is '%s', visit is %u, type is %u.\n",
			n->key, n->visit, n->type);
	}
	
	fprintf(stdout, "ht_table walker begin with '%s' now...\n", keyword);
	if (ht_walker_from(dict, keyword) < 0) {
		fprintf(stdout, "ht_table walker set node error.\n");
	}
	if (ht_walker(dict, _walker, &i) < 0) {
		fprintf(stdout, "ht_table walker set node error.\n");
	}

	fprintf(stdout, "ht_table del '%s' now...\n", keyword);
	if (ht_del(dict, keyword) < 0) {
		fprintf(stdout, "ht_table del '%s' failure.\n", keyword);
	} else {
		fprintf(stdout, "ht_table del '%s' successfully.\n", keyword);
	}
	
	n = (S_VAL *)ht_get(dict, keyword);
	if (n == NULL) {
		fprintf(stdout, "ht_table get '%s' not exist.\n", keyword);
	} else {
		fprintf(stdout, "ht_table get '%s' successfully.\n", keyword);
		fprintf(stdout, "key is '%s', visit is %u, type is %u.\n",
			n->key, n->visit, n->type);
	}
	
	ht_dump(dict);
	
	ht_exit(dict);
	fprintf(stdout, "ht_table test exit.\n");
	
	return 0;
}
